package com.owg.jigsaw;

import java.util.Queue;

import com.owg.jigsaw.slots.Slot;

import owg.util.data.PField;
import owg.util.data.PFieldImmutable;
import owg.util.data.PFieldList;
import owg.util.data.ReferenceSet;
import owg.util.data.Referencer;
import javafx.geometry.Point2D;
import javafx.scene.layout.Pane;

public abstract class WPane implements WNode, WSingleFieldContainer<WBlock>
{	
	protected final WRoot root;
	protected Pane pane;
	
	public final PFieldList<WBlock> children = new PFieldList<>(this, WBlock.class, 0, -1);
	protected final Referencer referencer = new ReferenceSet();
	public final boolean isPalette;
	
	public WPane(WRoot root, boolean isPalette, Pane ui)
	{
		this.isPalette = isPalette;
		this.root = root;
		this.pane = ui;
	}
	
	public Pane getUI()
	{
		if(pane == null)
			pane = makeUI();
		return pane;
	}
	
	protected abstract Pane makeUI();

	@Override
	public void addNotify(PFieldImmutable<?> newField)
	{
		assert root == newField.getOwner() : this+" cannot be added to a different root than it was initialized with!";
	}
	@Override
	public void removeNotify(PFieldImmutable<?> fromField)
	{
		assert root == fromField.getOwner() : this+" cannot be removed from a different root than it was initialized with!";
	}
	@Override
	public PField<WBlock> getChildren()
	{
		return children;
	}
	
	@Override
	public WContainer<?> getParent()
	{
		return root;
	}
	@Override
	public WRoot getRoot()
	{
		return root;
	}

	public abstract BlockDropAction accepts(WBlock b);

	@Override
	public void putTargetSlots(Queue<Slot> sq)
	{
		if(isPalette)
			return;
		for(WBlock c : children)
		{
			c.putTargetSlots(sq);
		}
			
	}
	/**Returns the block at the indicated position in local space. 
	 * If the position is out of bounds, then this will return null.*/
	public WBlock getBlockAt(Point2D panePoint)
	{
		for(WBlock c : children)
		{
			Pane ui = c.getUI();
			Point2D blkPoint = ui.sceneToLocal(pane.localToScene(panePoint));
			WBlock blk = c.getBlockAt(blkPoint);
			if(blk != null)
				return blk;
		}
		return null;
	}
}
